<?php

namespace api\controller;

// +----------------------------------------------------------------------
// | 项目数据控制层
// +----------------------------------------------------------------------

use common\controller\VerifyController;
use common\service\EpisodeShowingsNumberTreeService;
use common\service\ProjectService;
use common\service\ProjectStepReviewWorkflowRelationService;
use common\service\ProjectWarningService;
use common\service\TaskStatisticsService;
use common\service\TemplateService;
use common\validate\Project as ProjectValidate;
use support\ErrorCode;
use think\Exception;
use think\module\Module;
use think\Request;
use think\Response;

class ProjectController extends VerifyController
{

    /** @var ProjectService */
    protected $projectService;
    /** @var TaskStatisticsService */
    private $taskStatisticsService;
    /** @var TemplateService */
    protected $projectTemplateService;
    /** @var EpisodeShowingsNumberTreeService */
    private $episodeShowingsNumberTreeService;
    /** @var ProjectStepReviewWorkflowRelationService */
    private $projectStepReviewWorkflowRelationService;
    /** @var ProjectWarningService */
    private $projectWarningService;

    public function __construct()
    {
        parent::__construct();
        $this->projectService = ProjectService::getInstance();
        $this->taskStatisticsService = new TaskStatisticsService();
        $this->projectTemplateService = TemplateService::getInstance();
        $this->episodeShowingsNumberTreeService = EpisodeShowingsNumberTreeService::getInstance();
        $this->projectStepReviewWorkflowRelationService = new ProjectStepReviewWorkflowRelationService();
        $this->projectWarningService = ProjectWarningService::getInstance();
    }

    /**
     * 获得项目列表
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function getList(Request $request)
    {
        $filterRoleResourceByProjectMember = $request->param()['param']['filter_role_resource_by_project_member'] ?? 'no';
        $filterRoleResourceByProjectMember = $filterRoleResourceByProjectMember === 'yes';
        $appCode = $request->param()['param']['app_code'] ?? null;
        if ($filterRoleResourceByProjectMember && empty($appCode)) {
            throw_strack_exception('param.app_code required', ErrorCode::DATA_INVALID);
        }
        $res = $this->projectService->getUserProjectList($request->getUserId(), $request->param(), $filterRoleResourceByProjectMember, $appCode);
        return json(success_response('', $res));
    }

    /**
     * 删除项目
     * @param Request $request
     * @return Response
     * @throws \Throwable
     */
    public function delete(Request $request)
    {
        $res = $this->projectService->delete($request->param());
        return json(success_response('', $res));
    }

    /**
     * 获得团队成员项目列表
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function getTeamUserProjectList(Request $request)
    {
        $res = $this->projectService->getTeamUserProjectList($request->param()['param']['user_id'], $request->param());
        return json(success_response('', $res));
    }

    /**
     * 创建项目
     * @param Request $request
     * @return Response
     * @throws \Throwable
     */
    public function create(Request $request)
    {
        $param = $request->param();
        $param['module_code'] = $request->getModuleCode();
        $res = $this->projectService->create($param, Module::$moduleDictData['module_index_by_code'][$request->getModuleCode()]);
        return json(success_response('', $res));
    }

    /**
     * 项目 update
     * @param Request $request
     * @return Response
     */
    public function update(Request $request)
    {
        $data = $request->param()['data'];
        $throwNoDataUpdateException = $request->param()['throw_no_data_change_exception'] ?? 'yes';
        $throwNoDataUpdateException = $throwNoDataUpdateException === 'yes';
        //检测项目模板没有目录模板则不能选择此项目模板
        try {
            $res = $this->projectService->update($data, Module::$moduleDictData['module_index_by_code'][$request->getModuleCode()], $throwNoDataUpdateException);
            return json(success_response('', $res));
        } catch (\think\exception\HttpResponseException $e) {
            throw $e;
        } catch (\Throwable $e) {
            throw_strack_exception($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 单表项目查询
     * @param Request $request
     * @return Response
     */
    public function baseSelect(Request $request)
    {
        $param = $request->param();
        $res = $this->projectService->baseSelect($param['param']);
        return json(success_response('', $res));
    }

    /**
     * 快速流程设置
     * @return Response
     * @throws Exception
     */
    public function setFastFlow(Request $request)
    {
        $res = $this->projectService->setFastFlow($request->param(['data']));
        return json(success_response('', $res));
    }

    /**
     * 根据集所属状态获取集数列表
     * @param Request $request
     * @return Response
     */
    public function getEpisodeList(Request $request)
    {
        $param = $request->param()['param'];
        $onlyShowResponsible = $param['only_show_responsible'] ?? 'no';
        $onlyShowResponsibleFilter = $param['only_show_responsible_filter'] ?? '';
        $page = $param['page'] ?? [];
        $userId = $request->getUserId();
        $res = $this->episodeShowingsNumberTreeService->getEpisodeList($param['project_id'], $param['episode_status'], $param['count_type'], $userId, $page, $onlyShowResponsible === 'yes', $onlyShowResponsibleFilter);
        return json(success_response('OK', $res));
    }

    /**
     * 根据集数ID获取场次列表
     * @param Request $request
     * @return Response
     */
    public function getShowingNumberListByEpisode(Request $request)
    {
        $param = $request->param()['param'];
        $res = $this->episodeShowingsNumberTreeService->getShowingNumberListByEpisode($param['project_id'], $param['episode_id']);
        return json(success_response('OK', $res));
    }

    /**
     * 查询集场树
     * @param Request $request
     * @return Response
     */
    public function episodeShowingNumberTree(Request $request)
    {
        $param = $request->param()['param'];
        $showTotal = $param['show_total'] ?? 'no';
        $dataFilter = $param['data_filter'] ?? null;
        $includeShowingsNumber = $param['include_showings_number'] ?? 'yes';
        $includeShowingsNumber = $includeShowingsNumber === 'yes';
        $filter = $param['filter'];
        $countDataSource = $param['count_data_source'] ?? null;
        $chunkSize = $param['episode_chunk_size'];
        $userId = $request->getUserId();

        $entityDataFilter = $param['entity_data_filter'] ?? null;
        $isQueryUp = $param["is_query_up"] ?? "no";

        $res = $this->episodeShowingsNumberTreeService->episodeShowingNumberTree($filter, $userId, $chunkSize, $showTotal === 'yes', $dataFilter, $includeShowingsNumber, $countDataSource, $entityDataFilter, $isQueryUp);
        return json(success_response('OK', $res));
    }

    /**
     * 获得项目模块字段规则配置
     * @param Request $request
     * @return Response
     */
    public function getModuleFieldRuleSetting(Request $request)
    {
        $res = $this->projectService->getModuleFieldRuleSetting($request->param()['param']['filter']);
        return json(success_response('OK', $res));
    }

    /**
     * 任务完成统计
     * @param Request $request
     * @return Response
     */
    public function taskDoneCount(Request $request)
    {
        $filter = $request->param()['param']['filter'];
        $episodeCodes = $filter['episode_code'] ?? [];
        $stepCategoryIdList = $filter['step_category_id_list'] ?? [];
        $projectId = $filter['project_id'];
        $taskPlanEndTime = $filter['task_plan_end_time'] ?? [];
        $category = $filter['category_name'] ?? '';
        if (!empty($taskPlanEndTime)) {
            $taskPlanEndTime = array_map(function ($item) {
                return strtotime($item);
            }, $taskPlanEndTime);
        }
        $moduleCode = $filter['module_code'] ?? 'asset';
        $countType = $filter['count_type'] ?? 'step';
        $res = $this->taskStatisticsService->taskDoneCount($projectId, $episodeCodes, $moduleCode, $category, $taskPlanEndTime, $stepCategoryIdList, $countType);
        return json(success_response('OK', $res));
    }

    /**
     * 复制项目模板配置到项目配置 (不会重复复制)
     * @param Request $request
     * @return Response
     */
    public function copyProjectTemplateRelateConfig(Request $request)
    {
        $projectId = $request->param()['param']['project_id'];
        $res = $this->projectService->copyProjectTemplateRelateConfig($projectId);
        return json(success_response('OK', $res));
    }

    /**
     * 查询项目审核关系树
     * @param Request $request
     * @return Response
     */
    public function selectProjectReviewRelationTree(Request $request)
    {
        $projectId = $request->param()['param']['project_id'];
        $workflowFilter = $request->param()['param']['filter'];
        $res = $this->projectStepReviewWorkflowRelationService->selectProjectReviewRelationTree($projectId, $workflowFilter);
        return json(success_response('OK', $res));
    }

    /**
     * 查询项目工序流审核关系树
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function selectProjectStepWorkflowReviewRelationTree(Request $request)
    {
        $param = $request->param()['param'];
        $projectId = $param['filter']['project_id'];
        $stepWorkflowId = $param['filter']['step_workflow_id'];
        $res = $this->projectStepReviewWorkflowRelationService->selectProjectStepWorkflowReviewRelationTree($projectId, $stepWorkflowId);
        return json(success_response('OK', $res));
    }

    /**
     * 保存工序审核流关联关系
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function saveProjectReviewRelation(Request $request)
    {
        $validate = new ProjectValidate();
        $validate->scene('SaveProjectReviewRelationItem');
        $dataList = $request->param()['data_list'];
        $projectId = $request->param()['project_id'];
        foreach ($dataList as $data) {
            if (!$validate->check($data)) {
                throw_strack_exception($validate->getError(), ErrorCode::REQUEST_PARAM_ERROR);
            }
        }
        $res = $this->projectStepReviewWorkflowRelationService->saveProjectReviewRelation($dataList, $projectId);
        return json(success_response('OK', $res));
    }

    /**
     * 保存审核点审核角色code数据
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function saveCheckListRoleCode(Request $request)
    {
        $validate = new ProjectValidate();
        $validate->scene('SaveCheckListRoleCodeItem');
        $dataList = $request->param()['data_list'];
        $projectId = $request->param()['project_id'];
        foreach ($dataList as $data) {
            if (!$validate->check($data)) {
                throw_strack_exception($validate->getError(), ErrorCode::REQUEST_PARAM_ERROR);
            }
        }
        $res = $this->projectStepReviewWorkflowRelationService->saveCheckListRoleCode($dataList, $projectId);
        return json(success_response('OK', $res));
    }

    /**
     * 保存所有审核配置数据
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function saveAllReviewData(Request $request)
    {
        $checkListRoleData = $request->param()['check_list_role_data'] ?? [];
        $reviewRelationData = $request->param()['review_relation_data'] ?? [];
        $projectId = $request->param()['project_id'];
        $res = [];
        $validate = new ProjectValidate();
        if (!empty($reviewRelationData)) {
            $validate->scene('SaveProjectReviewRelationItem');
            foreach ($reviewRelationData as $data) {
                if (!$validate->check($data)) {
                    throw_strack_exception($validate->getError(), ErrorCode::REQUEST_PARAM_ERROR);
                }
            }
            $res['review_relation_update'] = $this->projectStepReviewWorkflowRelationService->saveProjectReviewRelation($reviewRelationData, $projectId);
        }
        if (!empty($checkListRoleData)) {
            $validate->scene('SaveCheckListRoleCodeItem');
            foreach ($checkListRoleData as $data) {
                if (!$validate->check($data)) {
                    throw_strack_exception($validate->getError(), ErrorCode::REQUEST_PARAM_ERROR);
                }
            }
            $res['check_list_update'] = $this->projectStepReviewWorkflowRelationService->saveCheckListRoleCode($checkListRoleData, $projectId);
        }
        return json(success_response('OK', $res));
    }

    /**
     * 保存延期审核配置数据
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function saveDelayReviewData(Request $request)
    {
        try {
            $res = $this->projectStepReviewWorkflowRelationService->saveProjectDelayReviewRelation($request->param()['data']);
            return json(success_response('', $res));
        } catch (\Throwable $e) {
            throw_strack_exception($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 查询延期审核流配置
     * @param Request $request
     * @return Response
     * @throws \Exception
     */
    public function selectDelayReviewRelation(Request $request)
    {
        $res = $this->projectStepReviewWorkflowRelationService->selectDelayReviewRelation($request->param()['param']['filter']);
        return json(success_response('', $res));
    }

    /**
     * 项目配置检测
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    public function projectConfigCheck(Request $request)
    {
        $res = $this->projectService->projectConfigCheck($request->param()['param']['filter']['id']);
        return json(success_response('OK', $res));
    }

    public function projectConfigMessageReceiverFind(Request $request)
    {
        $param = query_array_construct([
            'project_id' => 'intval',
            'step_category_id' => 'split_array|array_map,intval',
            'role_code_list' => 'split_array|array_map,strval',
        ], $request->param()['param'] ?? []);
        $res = $this->projectService->projectConfigMessageReceiverFind($param);
        return json(success_response('success', $res));
    }

    public function projectConfigMessageReceiverSave(Request $request)
    {
        $param = query_array_construct([
            'project_id' => 'intval',
            'step_category_id' => 'intval',
            'receiver_list' => '',
        ], $request->param()['param'] ?? []);
        $res = $this->projectService->projectConfigMessageReceiverSave($param);
        return json(success_response('success', $res));
    }

    /**
     * 添加项目剧集
     * @param Request $request
     * @return Response
     * @throws \Throwable
     */
    public function addProjectEpisode(Request $request)
    {
        $data = $request->param()['data'];
        $res = $this->projectService->addProjectEpisode($data, $request->getUserId());
        return json(success_response('OK', $res));
    }

    /**
     * 删除项目剧集
     * @param Request $request
     * @return Response
     */
    public function deleteProjectEpisode(Request $request)
    {
        $data = $request->param()['param']['filter'];
        try {
            $res = $this->projectService->deleteProjectEpisode($data);
            return json(success_response('OK', $res));
        } catch (Exception $e) {
            throw_strack_exception($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 查询项目集关系树
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    public function projectEpisodeTree(Request $request)
    {
        $param = $request->param();
        $param["param"]["filter"]["tenant_id"] = $param["param"]["filter"]["tenant_id"] ?? $request->getTenantId();
        $res = $this->projectService->selectProjectEpisodeAllocationTree($param['param'], $request->getUserId());
        return json(success_response('', $res));
    }

    /**
     * 获得多个项目信息
     * @param Request $request
     * @return Response
     */
    public function getProjects(Request $request)
    {
        $param = $request->param();
        $filter = $param['param']['filter'] ?? [];
        $field = $param['param']['fields'] ?? '*';
        $res = $this->projectService->getProjects($filter, $field);
        return json(success_response('', $res));
    }

    /**
     * 获取项目统计工序分类配置
     * @param Request $request
     * @return Response
     */
    public function statisticalStepCategoryConfig(Request $request)
    {
        $res = $this->projectService->statisticalStepCategoryConfig();
        return json(success_response('', $res));
    }

    /**
     * 查询计划和实际人力资源
     * @param Request $request
     * @return Response
     */
    public function selectProduceResources(Request $request)
    {
        $param = $request->param();
        $res = $this->projectService->selectProduceResources($param['param']['filter']);
        return json(success_response('', $res));
    }

    /**
     * 查询人力资源分布
     * @param Request $request
     * @return Response
     */
    public function selectProduceResourcesDistributed(Request $request)
    {
        $param = $request->param();
        $res = $this->projectService->selectProduceResourcesDistributed($param['param']['filter']);
        return json(success_response('', $res));
    }

    /**
     * 查询得分和风险信息
     * @param Request $request
     * @return Response
     */
    public function getScoreAndErrorMessage(Request $request)
    {
        $projectId = $request->param()['param']['project_id'];
        $res = $this->projectWarningService->getScoreAndErrorMessage($projectId, 60);
        return json(success_response('', $res));
    }

    /**
     * 项目可显示分类列表
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    public function getShowStepCategoryList(Request $request)
    {
        $projectId = $request->param()['param']['project_id'] ?? 0;
        $includeStep = $request->param()['param']['include_step'] ?? 'no';
        $res = $this->projectService->getShowStepCategoryList($projectId, $includeStep === 'yes');
        return json(success_response('', $res));
    }

    /**
     * 获取显示工序分类组
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    public function getShowStepCategoryGroup(Request $request)
    {
        $res = $this->projectService->getShowStepCategoryGroup();
        return json(success_response('', $res));
    }

    /**
     * 查询产能配置
     * @param Request $request
     * @return Response
     */
    public function getPCConfig(Request $request)
    {
        $projectId = $request->param()['param']['filter']['project_id'];
        $stepCategoryIdList = $request->param()['param']['filter']['step_category_id_list'];
        $res = $this->projectService->getPCConfig($projectId, $stepCategoryIdList);
        return json(success_response('', $res));
    }

    /**
     * 保存产能配置
     * @param Request $request
     * @return Response
     */
    public function savePCConfig(Request $request)
    {
        $projectId = $request->param()['param']['project_id'];
        $stepCategoryIdList = $request->param()['param']['step_category_id_list'];
        $data = $request->param()['param']['config'];
        $res = $this->projectService->savePCConfig($projectId, $stepCategoryIdList, $data);
        return json(success_response('', $res));
    }

    /**
     * 查询产能等级配置
     * @param Request $request
     * @return Response
     */
    public function getPCLevelTransConfig(Request $request)
    {
        $projectId = $request->param()['param']['filter']['project_id'];
        $stepCategoryIdList = $request->param()['param']['filter']['step_category_id_list'];
        $res = $this->projectService->getPCLevelTransConfig($projectId, $stepCategoryIdList);
        return json(success_response('', $res));
    }

    /**
     * 保存产能等级配置
     * @param Request $request
     * @return Response
     */
    public function savePCLevelTransConfig(Request $request)
    {
        $projectId = $request->param()['param']['project_id'];
        $stepCategoryIdList = $request->param()['param']['step_category_id_list'];
        $data = $request->param()['param']['config'];
        $res = $this->projectService->savePCLevelTransConfig($projectId, $stepCategoryIdList, $data);
        return json(success_response('', $res));
    }

    /**
     * 关联双方项目id
     * @param Request $request
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getProjectBelongProjectId(Request $request)
    {
        $projectId = $request->param()['project_id'];

        $res = $this->projectService->getProjectByBelongProjectId($projectId);

        return json(success_response('', $res));
    }

}
